﻿using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ufida.u9.ait.openapi.utils;
using UFIDA.U9.CUST.AITBarCodeBE;

namespace UFIDA.U9.CUST.AITBarCodeBP.utils
{
    internal class BarCodeUtils
    {
        public static PrintRule GetPrintRule(string printTemplateID, BarcodeRuleConfiguration config)
        {
            foreach(var print in config.prints)
            {
                if(print.printTemplateID == printTemplateID)
                    return print;
            }
            throw new Exception($"条码配置,依据模板ID[{printTemplateID}]查找打印规则失败!");
        }

        /// <summary>
        /// 从文件加载BarcodeRuleConfiguration
        /// </summary>
        /// <param name="filePath"></param>
        /// <returns></returns>
        public static BarcodeRuleConfiguration LoadBarcodeRuleConfig()
        {
            // 读取U9参数
            string filePath = U9Utils.GetU9SysParam("BARCODERULE_FILE");
            if (string.IsNullOrEmpty(filePath)) throw new Exception("参数[移动条码配置文件路径]未设置");
            // 读取文件内容
            BarcodeRuleConfiguration config = JSONUtils.ReadJSONFile<BarcodeRuleConfiguration>(filePath);

            return config;
        }
        /// <summary>
        /// 依据条码实体,计算获取条码值
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public static string GetBarcode(long id)
        {
            string barcode = "";
            AITBarCode be = AITBarCode.Finder.FindByID(id);
            if (be == null) throw new Exception("依据ID获取条码实体失败!");
            BarcodeRuleConfiguration config = LoadBarcodeRuleConfig();
            if (be.Item == null) throw new Exception("该条码实体的料品为空");

            //获取条码配置
            BarcodeRule rule = GetBarRule(be.Item.Code, config);
            //依据条码配置生成条码值
            barcode = BuildBarCode(be, rule);
            return barcode;
        }
        /// <summary>
        /// 依据条码实体和条码规则,构造条码值
        /// </summary>
        /// <param name="bar">条码实体</param>
        /// <param name="rule">条码规则</param>
        /// <returns>条码值</returns>
        private static string BuildBarCode(AITBarCode bar, BarcodeRule rule)
        {
            string barcode;
            //依据条码规则字段设置,运行OQL,获取条码字段值
            List<string> selects = new List<string>();
            foreach (var item in rule.lines)
            {
                if (item.isSerial) continue;
                selects.Add($" {item.metadata} as {item.code} ");
            }
            string selectStr = string.Join(",", selects);
            //运行OQL,获取条码字段值
            string entityName = AITBarCode.EntityRes.BE_FullName.Replace(".", "::");
            string oql = $"select {selectStr} from {entityName} where ID={bar.ID}";
            List<Dictionary<string, object>> datalist = U9Utils.RunOql(oql);
            if (datalist.Count == 0) throw new Exception($"查询不到数据,OQL:{oql}");
            //依据OQL返回值拼接条码前缀
            List<string> values = new List<string>();
            foreach (var item in rule.lines)
            {
                if (item.isSerial) continue;
                object fval = datalist[0][item.code];
                if (fval == null) throw new Exception($"字段[{item.name}]为空");
                if (string.IsNullOrEmpty(fval.ToString()) && item.required)
                    throw new Exception($"字段[{item.code}]值为空");
                if (!item.isSerial)
                {
                    if(fval is decimal)
                    {
                        //decimal类型,去掉尾部0
                        decimal dval=(decimal)fval;
                        values.Add(dval.ToString("0.############"));
                    }
                    else
                    {
                        values.Add(fval.ToString());
                    }
                    
                }
            }
            string pref = string.Join(rule.delimiter, values) + rule.delimiter;

            //依据条码前缀获取流水号
            int seq = 1;
            string sql = $"select max(BarCode) BarCode from AIT_BarCode where BarCode like '{pref}%'";
            List<Dictionary<string, object>> datalist1 = U9Utils.RunSQL(sql);
            object bar1 = datalist1[0]?["BarCode"];
            if (bar1 != null && !string.IsNullOrEmpty(bar1.ToString()))
            {
                string seqStr = bar1.ToString().Substring(pref.Length);
                seq = int.Parse(seqStr) + 1;
            }
            barcode = pref + seq.ToString("D5");
            return barcode;
        }

        /// <summary>
        /// 获取config中的配置规则
        /// </summary>
        /// <param name="itemCode">料号</param>
        /// <param name="config">配置规则</param>
        /// <returns>条码规则</returns>
        private static BarcodeRule GetBarRule(string itemCode, BarcodeRuleConfiguration config)
        {
            string ruleCode = "";
            foreach (var item in config.assign)
            {
                string[] cats = item.category.Split(',');
                foreach (string cat in cats)
                {
                    //料号前缀匹配
                    if (itemCode.StartsWith(cat))
                    {
                        ruleCode = item.ruleCode;
                        break;
                    }
                }
            }
            BarcodeRule rule = config.rules.Find(item => item.code == ruleCode);
            if (rule == null) throw new Exception($"依据料号[{itemCode}]获取条码配置失败");
            return rule;
        }
    }
}
